package biz.datalk.industrialland.admin.modules.common.controller;

import biz.datalk.commons.utils.ip.IPUtil;
import biz.datalk.industrialland.common.result.UnifyResult;
import biz.datalk.industrialland.common.util.RedisUtil;
import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.LoggerContext;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.Objects;

/**
 * 只针对 logback
 * 动态变更日志级别
 *
 * @author tarofang@163.com
 * @date 2020-12-07
 */
@Slf4j
@RestController
@RequestMapping("/api/dynLogger")
public class DynLoggerController {

    final String[] levels = {"OFF", "FATAL", "ERROR", "WARN", "INFO", "DEBUG", "TRACE", "ALL"};

    @Autowired
    private RedisUtil redisUtil;

    @RequestMapping(value = "/updateLogbackLevel")
    public UnifyResult updateLogbackLevel(HttpServletRequest request) {
        // @RequestParam(value = "level") String level,
        // @RequestParam(value = "packageName", defaultValue = "-1") String packageName
        String ip = IPUtil.getIpAddress(request);
        String ips = redisUtil.getStr("IP:LIMITS:API:DYN_LOGGER__UPDATE_LOGBACK_LEVEL", "127.0.0.1,localhost");
        if (!ips.contains(ip)) {
            return UnifyResult.fail("没有权限");
        }

        String packageName = Objects.toString(StringUtils.trimToNull(request.getParameter("packageName")), "root");
        String level = StringUtils.trimToEmpty(request.getParameter("level"));
        if (!isAllowed(level)) {
            return UnifyResult.fail("Invalid level");
        }

        Logger logger = getLoggerContext().getLogger(packageName);
        if (logger == null) {
            return UnifyResult.fail("Invalid packageName");
        }

        logger.setLevel(Level.toLevel(level));
        log.debug("set logger level: [level={}, packageName={}]", level, packageName);

        return UnifyResult.success();
    }


    /**
     * 判断是否是合法的日志级别
     *
     * @param level 日志等级
     *
     * @return boolean
     */
    private boolean isAllowed(String level) {
        return Arrays.asList(levels).contains(level.toUpperCase());
    }

    private void setLevel(String packageName, String level) {
        getLoggerContext().getLogger(packageName).setLevel(Level.toLevel(level));
    }

    private String getLevel(String packageName) {
        Logger logger = getLoggerContext().getLogger(packageName);
        return hasNull(logger, logger.getLevel()) ? "" : logger.getLevel().toString();
    }

    private boolean hasNull(Object... objects) {
        if (Objects.nonNull(objects)) {
            for (Object element : objects) {
                if (null == element) {
                    return true;
                }
            }
        }
        return false;
    }


    private LoggerContext getLoggerContext() {
        return (LoggerContext) LoggerFactory.getILoggerFactory();
    }


}
